package com.radar.common;

import org.locationtech.jts.geom.Coordinate;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("all")
/**
 * @author: fy-wbj
 * @description: 风向杆
 * @date: 2020/3/23
 */
public class WindFlagSymbol {

    // 每一个风杆y间距
    private float ystep = 0.15F;

    // 海流
    private float streamstep = 0.4F;

    // 海流
    private float streamShort = 0.15F;

    // 长杆
    private float flagLong = 0.4F;

    // 短杆
    private float flagShort = 0.25F;

    // 风速
    private double windv;

    public double getWindv() {
        return windv;
    }

    public void setWindv(double windv) {
        this.windv = windv;
    }

    public class WindFlagLine {
        private Coordinate a = new Coordinate(0, 0);

        public Coordinate getA() {
            return a;
        }

        @Override
        public String toString() {
            return "WindFlagLine [a=" + a + ", b=" + b + "]";
        }

        public void setA(Coordinate a) {
            this.a = a;
        }

        private Coordinate b = new Coordinate(0, 0);

        public Coordinate getB() {
            return b;
        }

        public void setB(Coordinate b) {
            this.b = b;
        }

        public double minx() {
            return Math.min(a.getX(), b.getX());
        }

        public double miny() {
            return Math.min(a.getY(), b.getY());
        }

        public double maxx() {
            return Math.max(a.getY(), b.getY());
        }

        public double maxy() {
            return Math.max(a.getY(), b.getY());
        }
    }

    private ArrayList<WindFlagLine> lines;

    /**
     * 风向杆 构造器
     *
     * @param windv
     */
    public WindFlagSymbol(double windv) {
        this.windv = windv;
        createFlagLines();
    }

    /**
     * 海流 无风羽 构造器
     */
    public WindFlagSymbol() {
        createFlagArrow();
    }

    public WindFlagSymbol(double step, boolean isDir) {
        this.streamShort *= step;
        this.streamstep *= step;
        createFlagArrow();
    }


    // 生成海流(杆)
    public void createFlagArrow() {
        lines = new ArrayList<>();

        WindFlagLine line = new WindFlagLine();
        line.a = new Coordinate(0, 0);
        line.b = new Coordinate(0, 1);
        lines.add(line);


        line = new WindFlagLine();
        line.a = new Coordinate(streamShort, 1 - (streamstep / 2));
        line.b = new Coordinate(0 - streamShort, 1 - (streamstep / 2));
        lines.add(line);

        line = new WindFlagLine();
        line.a = new Coordinate(0, 1 + (streamstep / 2));
        line.b = new Coordinate(streamShort, 1 - (streamstep / 2));
        lines.add(line);

        line = new WindFlagLine();
        line.a = new Coordinate(0, 1 + (streamstep / 2));
        line.b = new Coordinate(0 - streamShort, 1 - (streamstep / 2));
        lines.add(line);
    }

    @SuppressWarnings("squid:S3776")
    // 生成风向(杆)
    private void createFlagLines() {
        lines = new ArrayList<>();
        int lnum20 = 0;
        int lnum4 = 0;
        int lnum2 = 0;
        double v = Math.floor(windv);
        lnum20 = (int) (v / 20);
        v = v - lnum20 * 20;
        if (v < 20 && v > 18) {
            lnum20++;
        } else {
            lnum4 = (int) (v / 4);
            v = v - lnum4 * 4;
            if (v < 4 && v > 2) {
                lnum4++;
            } else {
                lnum2 = (int) (v / 2);
                v = v - lnum2 * 2;
                if (v < 2 && v > 0) {
                    lnum2++;
                }
            }
        }


        WindFlagLine line = new WindFlagLine();
        line.a = new Coordinate(0, 0);
        line.b = new Coordinate(0, 1);
        lines.add(line);

        //风速 =1，就一根棍子  或者为0
        if ((int) Math.floor(windv) == 1 || ((int) Math.floor(windv) == 0)) {
            return;
        }
        //风速 =2，
        if ((int) Math.floor(windv) == 2) {
            line = new WindFlagLine();
            line.a = new Coordinate(0, 1 - ystep);
            line.b = new Coordinate(flagShort, 1 - ystep);
            lines.add(line);
            return;
        }

        float topy = 1;
        if (lnum20 > 0) {
            for (int i = 0; i < lnum20; i++) {
                line = new WindFlagLine();
                line.a = new Coordinate(0, topy);
                line.b = new Coordinate(flagLong, topy - ystep);
                lines.add(line);

                line = new WindFlagLine();
                line.a = new Coordinate(flagLong, topy - ystep);
                line.b = new Coordinate(0, topy - 2 * ystep);
                lines.add(line);
                topy = topy - 3 * ystep;
            }
        }
        if (lnum4 > 0) {
            for (int i = 0; i < lnum4; i++) {
                line = new WindFlagLine();
                line.a = new Coordinate(0, topy);
                line.b = new Coordinate(flagLong, topy);
                lines.add(line);
                topy = topy - ystep;
            }
        }
        if (lnum2 > 0) {
            for (int i = 0; i < lnum2; i++) {
                line = new WindFlagLine();
                line.a = new Coordinate(0, topy);
                line.b = new Coordinate(flagShort, topy);
                lines.add(line);
                topy = topy - ystep;
            }
        }
    }

    public void rotateTo(double angle) {
        angle = angle - 180;
        double da = angle * Math.PI / 180.0;// (-angle + 90 + 180) * Math.PI / 180.0;//-angle * Math.PI / 180.0;
//        double da = (-angle + 90 - 180) * Math.PI / 180.0;// (-angle + 90 + 180) * Math.PI / 180.0;//-angle * Math.PI / 180.0;
        for (int i = 0; i < lines.size(); i++) {
            Coordinate pfA = lines.get(i).a;
            Coordinate pfB = lines.get(i).b;
            WindFlagLine line = new WindFlagLine();
            line.a = new Coordinate((float) (pfA.getX() * Math.cos(da) + pfA.getY() * Math.sin(da)),
                    (float) (pfA.getY() * Math.cos(da) - pfA.getX() * Math.sin(da)));
            line.b = new Coordinate((float) (pfB.getX() * Math.cos(da) + pfB.getY() * Math.sin(da)),
                    (float) (pfB.getY() * Math.cos(da) - pfB.getX() * Math.sin(da)));
            lines.set(i, line);
        }
    }

    public void rotateTo(double u, double v) {
        this.rotateTo(getDirAndSpeed(u, v));
    }

    /**
     * 获得风杆数据 gis 里Y是反向
     *
     * @param centerp
     * @param radius
     * @return
     */
    public List<WindFlagLine> getActualLines(Coordinate centerp, double radius) {
        List<WindFlagLine> alines = new ArrayList<>();
        for (int i = 0; i < lines.size(); i++) {
            Coordinate pfA = lines.get(i).a;
            Coordinate pfB = lines.get(i).b;
            WindFlagLine line = new WindFlagLine();
            line.a = new Coordinate(centerp.getX() - pfA.getX() * radius,
                    centerp.getY() - pfA.getY() * radius);
            line.b = new Coordinate(centerp.getX() - pfB.getX() * radius,
                    centerp.getY() - pfB.getY() * radius);
            alines.add(line);
        }
        return alines;
    }

    /**
     * awt 里y是正向
     *
     * @param centerp
     * @param radius
     * @return
     */
    public List<WindFlagLine> getAwtActualLines(Coordinate centerp, double radius) {
        List<WindFlagLine> alines = new ArrayList<>();
        for (int i = 0; i < lines.size(); i++) {
            Coordinate pfA = lines.get(i).a;
            Coordinate pfB = lines.get(i).b;
            WindFlagLine line = new WindFlagLine();
            line.a = new Coordinate(centerp.getX() - pfA.getX() * radius,
                    centerp.getY() + pfA.getY() * radius);
            line.b = new Coordinate(centerp.getX() - pfB.getX() * radius,
                    centerp.getY() + pfB.getY() * radius);
            alines.add(line);
        }
        return alines;
    }

    public List<Line2D> getAwtLines(Coordinate centerp, double radius) {
        List<WindFlagLine> actualLines = getAwtActualLines(centerp, radius);
        List<Line2D> lines = new ArrayList<>();
        actualLines.forEach(line -> lines.add(new Line2D.Double(
                line.getA().getX(),
                line.getA().getY(),
                line.getB().getX(),
                line.getB().getY()
        )));
        return lines;
    }

    private Rectangle actRectF;

    public Rectangle getActRectF() {
        return actRectF;
    }

    public void setActRectF(Rectangle actRectF) {
        this.actRectF = actRectF;
    }

    /**
     * u v -> dir
     *
     * @param ud
     * @param vd
     * @return
     */
    public static double getDirAndSpeed(double u, double v) {
        double windAbs = Math.sqrt(Math.pow(u, 2) + Math.pow(v, 2));
        double windDirTrigTo = Math.atan2(u / windAbs, v / windAbs);
        double windDirTrigToDegrees = windDirTrigTo * 180 / Math.PI;
        double windDirTrigFromDegrees = windDirTrigToDegrees + 180;
        return windDirTrigFromDegrees;
        //计算角度
//        double dird = Math.atan(ud / vd) * 180 / Math.PI;
//        if (ud != 0 && vd < 0) {
//            dird = dird + 180;
//        } else if (ud < 0 && vd > 0) {
//            dird = dird + 360;
//        } else if (ud == 0 && vd > 0) {
//            dird = 0;
//        } else if (ud == 0 && vd < 0) {
//            dird = 180;
//        } else if (ud > 0) {
//            dird = 90;
//        } else if (ud < 0) {
//            dird = 270;
//        } else if (ud == 0) {
//            dird = -999;
//        }ｕ
//        return dird;
//        DecimalFormat df = new DecimalFormat("#.000")
//        return Double.parseDouble(df.format(windDirTrigFromDegrees));
    }

    /**
     * u v -> dir
     *
     * @param ud
     * @param vd
     * @return
     */
    public static double getDirAndSpeed180(double ud, double vd) {
        double dird = getDirAndSpeed(ud, vd);
        dird -= 180;
        if (dird < 0) {
            dird += 360;
        }
        return dird;
    }

    /**
     * 16 风向
     *
     * @param value
     * @return
     */
    public static double positionToDir(String value) {
        double dir = GisConstants.UNDEF;
        if (value == null) {
            dir = GisConstants.UNDEF;
        } else if (value.equals("N")) {
            dir = 360;
        } else if (value.equals("NNE")) {
            dir = 22.5;
        } else if (value.equals("NE")) {
            dir = 45;
        } else if (value.equals("ENE")) {
            dir = 67.5;
        } else if (value.equals("E")) {
            dir = 90;
        } else if (value.equals("ESE")) {
            dir = 112.5;
        } else if (value.equals("SE")) {
            dir = 135;
        } else if (value.equals("SSE")) {
            dir = 157.5;
        } else if (value.equals("S")) {
            dir = 180;
        } else if (value.equals("SSW")) {
            dir = 202.5;
        } else if (value.equals("SW")) {
            dir = 225;
        } else if (value.equals("WSW")) {
            dir = 247.5;
        } else if (value.equals("W")) {
            dir = 270;
        } else if (value.equals("WNW")) {
            dir = 292.5;
        } else if (value.equals("NW")) {
            dir = 315;
        } else if (value.equals("NNW")) {
            dir = 337.5;
        }
        return dir;
    }

    public static double U(double dSp, double dWrd) {
        if (dSp < 0){
            return 0;
        }
        double d0 = 0;
        d0 = dSp * Math.cos((270 - dWrd) * Math.PI / 180);
        return d0;
    }

    public static double V(double dSp, double dWrd) {
        if (dSp < 0){
            return 0;
        }
        double d0 = 0;
        d0 = dSp * Math.sin((270 - dWrd) * Math.PI / 180);
        return d0;
    }

    public static void main(String[] args) throws IOException {
        String file = "/Users/xx/Desktop/test.png";
        WindFlagSymbol windFlagSymbol = new WindFlagSymbol(8.7);
        windFlagSymbol.rotateTo(309);
        List<Line2D> awtLines = windFlagSymbol.getAwtLines(new Coordinate(50, 50), 20);
        BufferedImage bufferedImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();
        graphics2D.setColor(Color.red);
        awtLines.forEach(line -> graphics2D.draw(line));
        graphics2D.setColor(Color.black);
        graphics2D.drawRect(50, 50, 4, 4);
        ImageIO.write(bufferedImage, "png", new File(file));
    }

}
